#include "YGRoot.h"

#include "YGDevice.h"
#include "YGInput.h"
#include "YGLog.h"
#include "YGRenderMethodManager.h"


#if (YG_OS_TYPE == YG_OS_TYPE_WINDOWSMOBILE)

	#include "WM6\YGRootWM6.h"

#endif

namespace YoghurtGum
{

	Root* Root::s_Instance = NULL;

	Root::Root()
	{
		m_RendererTotal = 0;
		for (int i = 0; i < 8; i++)
		{
			m_RendererOptions[i] = NULL;
		}
		m_Renderer = NULL;
		m_Running = false;

		m_Window = Window::Create();
		m_Game = NULL;
	}

	Root::~Root()
	{

	}

	Root& Root::GetSingleton()
	{
		if (!s_Instance) { s_Instance = new Root(); }
		return *s_Instance;
	}

	RenderMethod* Root::GetRenderer()
	{
		return m_Renderer;
	}

	void Root::InstallRenderer(const char* a_PluginName)
	{	
		RenderMethodManager::Get().InstallRenderer(a_PluginName);
	}

	void Root::AttachGame(Game* a_Game)
	{
		m_Game = a_Game;
	}

	Game* Root::GetGame()
	{
		return m_Game;
	}

	Scene* Root::GetScene()
	{
		return m_Game->scene_current;
	}

	bool Root::Init()
	{
		//Log::GetSingleton().Print("Root::Init");

		Log::GetSingleton().Print("Root::Init");

		Device::Get().Init();

		Keyboard::Get().Init();
		TouchScreen::Get().Init();

		m_Window->Init();

		return true;
	}

	void Root::Resize(int a_Width, int a_Height)
	{
		Log::GetSingleton().Print("Root::Resize");

		Device::Get().Resize(a_Width, a_Height);
		if (m_Running)
		{
			if (m_Renderer) { m_Renderer->Resize(a_Width, a_Height); }
			if (m_Game) { m_Game->Resize(a_Width, a_Height); }
		}

		Log::GetSingleton().Print("Crash 1");
		TouchScreen::Get().Resize(a_Width, a_Height);
		Log::GetSingleton().Print("Crash 2");
	}

	bool Root::Start()
	{
		Log::GetSingleton().Print("Root::Start - Checking for game.");
		if (!m_Game) 
		{
			Log::GetSingleton() << "No game attached, exiting." << ENDL;
			return false; 
		}

		Log::GetSingleton().Print("Root::Start - Checking for RenderMethod.");
		m_Renderer = RenderMethodManager::Get().ChooseRenderMethod(m_Window);
		if (!m_Renderer)
		{
			Log::GetSingleton() << "Could not find a suitable render method." << ENDL;
			return false;
		}

		m_Game->Init();

#ifdef YG_USE_FIXED_TIMESTEP

		m_PhysicsTime = 0.f;
		m_PhysicsStart = YG_TIMER();

#endif

		m_Running = true;

		return true;
	}

	bool Root::Run()
	{
		if (!Init()) { return false; }

		m_Running = true;
		while (m_Running) 
		{ 
			Update(); 
			Render();
		}

		Destroy();		

		return true;
	}

	void Root::SetProperty(Property a_Property, const char* a_Value)
	{
		switch (a_Property)
		{
		case PROP_WINDOWTITLE:
			{
				m_Window->SetName(a_Value);
				break;
			}
		case  PROP_RENDERER:
			{
				m_Renderer = RenderMethodManager::Get().GetRenderMethod(a_Value);
				break;
			}
		}
	}

	bool Root::Update()
	{
		if (!m_Running) { return false; }

		Keyboard::Get().Update();

		if (!m_Game) { return false; }

#ifdef YG_USE_FIXED_TIMESTEP

		m_PhysicsCurrent = YG_TIMER();
		float delta = (float)(m_PhysicsCurrent - m_PhysicsStart);
		m_PhysicsStart = m_PhysicsCurrent;

		m_PhysicsTime += delta;

		while (m_PhysicsTime > YG_FIXED_TIMESTEP)
		{
			m_Game->Update();

			m_PhysicsTime -= YG_FIXED_TIMESTEP;
		}

#else

		m_Game->Update();

#endif

		Keyboard::Get().Clear();
		TouchScreen::Get().Clear();

		return true;
	}

	bool Root::Render()
	{
		if (!m_Running) { return false; }

		if (m_Window->Update())
		{
			m_Renderer->Clear();

			m_Window->PreRender();
			m_Renderer->PreRender();
				m_Game->Render();
			m_Renderer->PostRender();
			m_Window->PostRender();
		}

		return true;
	}

	void Root::CloseDown()
	{
		m_Running = false;
	}

	void Root::Destroy()
	{
		m_Window->Close();

		RenderMethodManager::Get().Destroy();
	}

	bool Root::IsRunning()
	{
		return m_Running;
	}

	void Root::SetInstance(Root* a_Instance)
	{
		s_Instance = a_Instance;
	}

}; // namespace YoghurtGum